#ifndef MESSAGE_H
#define MESSAGE_H

#include <QTcpSocket>
#include <cassert>

struct Message {
    quint32 status;
    quint32 type;
    qint32 length;
    qint32 data;
};

enum MessageStatus : quint32 {
    MSG_OK = 0xdeadbeef
};

enum MessageType : quint32 {
    MSG_STRING = 1 << 0,
    MSG_REJECT = 1 << 1,
    MSG_GAME_START = 1 << 2,
    MSG_GAME_QUIT = 1 << 3,
    MSG_ACK_GAME = 1 << 4,
    MSG_QUERY_PREEMPT = 1 << 5,
    MSG_REPLY_PREEMPT = 1 << 6,
    MSG_GAME_INFO = 1 << 7,
    MSG_REQUEST_POST = 1 << 8,
    MSG_POST_CARDS = 1 << 9,
    MSG_GAME_OVER = 1 << 10
};

// message with optional string
static inline void sendMsg(QTcpSocket* socket, quint32 type, const QByteArray& ba, qint32 data = 0)
{
    assert(socket);
    Message m = {.status = MSG_OK, .type = type | MSG_STRING, .length = ba.size(), .data = data};
    socket->write(reinterpret_cast<char*>(&m), sizeof(m));
    socket->write(ba.data(), ba.size());
}

/*
static inline void sendMsg(QTcpSocket* socket, quint32 type, const QByteArray& ba)
{
    assert(socket);
    Message m = {.status = MSG_OK, .type = type | MSG_STRING, .length = ba.size(), .data = 0};
    socket->write(reinterpret_cast<char*>(&m), sizeof(m));
    socket->write(ba.data(), ba.size());
}
*/

// message without additional string
static inline void sendMsgW(QTcpSocket* socket, MessageType type, qint32 data = 0)
{
    assert(socket);
    Message m = {.status = MSG_OK, .type = type, .length = 0, .data = data};
    socket->write(reinterpret_cast<char*>(&m), sizeof(m));
}

// raw message
static inline void sendMsg(QTcpSocket* socket, void* m, int length)
{
    assert(socket);
    socket->write(reinterpret_cast<char*>(m), length);
}

static inline Message recvMsg(QTcpSocket* socket, QString* out = nullptr)
{
    Message m;
    socket->read(reinterpret_cast<char*>(&m), sizeof(m));
    if (m.status == MSG_OK && ((m.type & MSG_STRING) > 0)) {
        char *buf = new char[m.length];
        socket->read(buf, m.length);
        if (out)
            *out = QString::fromUtf8(buf, m.length);
        delete[] buf;
    }
    return m;
}

static inline Message recvMsg(QTcpSocket* socket, QByteArray* out = nullptr)
{
    Message m;
    socket->read(reinterpret_cast<char*>(&m), sizeof(m));
    if (m.status == MSG_OK && ((m.type & MSG_STRING) > 0)) {
        char *buf = new char[m.length];
        socket->read(buf, m.length);
        if (out)
            *out = QByteArray(buf, m.length);
        delete[] buf;
    }
    return m;
}

#endif // MESSAGE_H
